package com.xand.bt.terminal.market;

import java.util.ArrayList;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.xand.bt.terminal.util.BitcoinTerminalConst;

public class ConnectorMarketStore {

	private String connectorClassName;
	
	private Map<String, MarketReference> referencesHashedByName;
	
	private Map<String, MarketReferenceDepth> marketDepthHashedByReference;
	
	public ConnectorMarketStore(String connectorClassName) {
		this.connectorClassName = connectorClassName;
		
		this.referencesHashedByName = new HashMap<String, MarketReference>();
		this.marketDepthHashedByReference = new HashMap<String, MarketReferenceDepth>();
	}
	
	public String getConnectorClassName() {
		return this.connectorClassName;
	}
	
	public void addMarketReference(MarketReference marketReference) {
		this.referencesHashedByName.put(marketReference.getName(), marketReference);
		this.marketDepthHashedByReference.put(marketReference.getName(), new MarketReferenceDepth(marketReference.getName()));
	}
	
	public MarketReference getMarketReference(String name) {
		return this.referencesHashedByName.get(name);
	}
	
	public int addMarketLevel(MarketLevel marketLevel) {
		
		List<MarketLevel> levels = this.getOrderedLevelsForReferenceAndDirection(marketLevel.getReference(), marketLevel.getDirection());
		Map<Long, MarketLevel> levelsHashedByPrice = this.getHashedLevelsForReferenceAndDirection(marketLevel.getReference(), marketLevel.getDirection());
		
		levels.add(marketLevel);
		Collections.sort(levels);
		
		levelsHashedByPrice.put(marketLevel.getPrice(), marketLevel);
		
		return levels.indexOf(marketLevel);
		
	}
	
	public void updateMarketLevelVolume(String reference, int direction, long price, long newVolume) {
		
		Map<Long, MarketLevel> levelsHashedByPrice = this.getHashedLevelsForReferenceAndDirection(reference, direction);
		MarketLevel marketLevel = levelsHashedByPrice.get(price);
		
		marketLevel.setVolume(newVolume);
		
	}
	
	public void removeMarketLevel(String reference, int direction, long price) {
		
		List<MarketLevel> levels = this.getOrderedLevelsForReferenceAndDirection(reference, direction);
		Map<Long, MarketLevel> levelsHashedByPrice = this.getHashedLevelsForReferenceAndDirection(reference, direction);
		
		int levelNumToRemove = 0;
		for(int i = 0; i < levels.size(); i++) {
			
			MarketLevel level = levels.get(i);
			if(level.getPrice() == price) {
				levelNumToRemove = i;
				break;
			}
		}
		
		levels.remove(levelNumToRemove);
		levelsHashedByPrice.remove(price);
		
	}
	
	public MarketLevel getMarketLevel(String reference, int direction, long price) {
		
		Map<Long, MarketLevel> levelsHashedByPrice = this.getHashedLevelsForReferenceAndDirection(reference, direction);
		MarketLevel marketLevel = levelsHashedByPrice.get(price);
		
		return marketLevel;
	}
	
	public List<Long> getPricesForReferenceAndDirection(String reference, int direction) {
		
		List<MarketLevel> levels = this.getOrderedLevelsForReferenceAndDirection(reference, direction);
		
		List<Long> ret = new ArrayList<Long>();
		
		for(MarketLevel level : levels) {
			ret.add(level.getPrice());
		}
		
		return ret;
	}
	
	public int getMarketLevelIndex(String reference, int direction, long price) {
		
		List<MarketLevel> orderedLevels = this.getOrderedLevelsForReferenceAndDirection(reference, direction);
		
		int ret = -1;
		for(int i = 0; i < orderedLevels.size(); i++) {
			MarketLevel singleLevel = orderedLevels.get(i);
			
			if(singleLevel.getPrice() == price) {
				ret = i;
				break;
			}
		}
		
		return ret;
		
	}
	
	private List<MarketLevel> getOrderedLevelsForReferenceAndDirection(String reference, int direction) {
		
		List<MarketLevel> ret = null;
		
		MarketReferenceDepth depth = this.marketDepthHashedByReference.get(reference);
		
		if(direction == BitcoinTerminalConst.MARKET_LEVEL_DIRECTION_ASK) {
			ret = depth.getAsks();
		}else{
			ret = depth.getBids();
		}
		
		return ret;
	}
	
	private Map<Long, MarketLevel> getHashedLevelsForReferenceAndDirection(String reference, int direction) {
		
		Map<Long, MarketLevel> ret = null;
		
		MarketReferenceDepth depth = this.marketDepthHashedByReference.get(reference);
		
		if(direction == BitcoinTerminalConst.MARKET_LEVEL_DIRECTION_ASK) {
			ret = depth.getAsksHashedByPrice();
		}else{
			ret = depth.getBidsHashedByPrice();
		}
		
		return ret;
	}
	
}
